<!--
 * @Title:
 * @Descripttion:
 * @version: 2.0
 * @Author: tangyong
 * @Date: 2023-07-20 20:14:27
 * @LastEditors: tangyong
 * @LastEditTime: 2024-11-15 14:50:08
-->
<template>
  <div class="comp-code-editor">
    <div class="action-bar">
      <el-link :underline="false" @click="handleFormatClick">格式化</el-link>
    </div>
    <codemirror
      ref="jsonEditor"
      :style="{ height: '300px' }"
      v-model="code"
      v-bind="codeOptions"
      @change="handleChange"
    />
  </div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
  import { Codemirror } from "vue-codemirror";
  import { javascript } from "@codemirror/lang-javascript";
  import { js_beautify } from "js-beautify";
  const props = defineProps({
    modelValue: {
      type: String,
      default: ""
    },
    options: {
      type: Object,
      default: () => ({})
    }
  });

  const code = ref("");
  const isFullScreen = ref(false);
  const defaultOptions = {
    readOnly: true,
    tabSize: 2, // Tab键空格数
    indentUnit: 2, // 缩进位数
    mode: "application/json", // 模式
    theme: "light", // 主题
    lineWiseCopyCut: "true", // 在复制或剪切时没有选择文本，那么就会自动操作光标所在的整行
    showCursorWhenSelecting: true, // 在选择时是否显示光标
    lineNumbers: true, // 是否显示行号
    smartIndent: true, // 自动缩进
    autoCloseBrackets: true, // 自动补全括号
    matchBrackets: true, // 括号匹配 在光标点击紧挨{、]括号左、右侧时，自动突出显示匹配的括号 }、]
    styleActiveLine: true, // 光标行背景高亮
    line: true,
    autoRefresh: true,
    autoFormatOnLoad: true,
    // autofocus: true,
    foldGutter: true, // 可折叠代码标记
    lineWrapping: true, // 设置长代码换行
    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
    hintOptions: {
      completeSingle: false
    },
    extensions: [javascript()]
  };

  const codeOptions = Object.assign(defaultOptions, props.options);
  let _updateFromInner = false;
  watch(
    () => props.modelValue,
    () => {
      if (_updateFromInner) {
        _updateFromInner = false;
        return;
      }
      initData();
    },
    { immediate: true }
  );

  function initData() {
    if (!["application/json", "javascript"].includes(codeOptions.mode)) {
      code.value = props.modelValue;
      return;
    }
    try {
      JSON.parse(props.modelValue);
      code.value = js_beautify(props.modelValue);
    } catch(e) {
      code.value = props.modelValue;
    }
  }

  function handleFullscreenClick() {
    isFullScreen.value = !isFullScreen.value;
    let contentDom = document.querySelector(".app-layout__content");
    if (isFullScreen.value) {
      contentDom?.classList.add("z-index-5");
    } else {
      contentDom?.classList.remove("z-index-5");
    }
  }

  function handleFormatClick() {
    if (["application/json"].includes(codeOptions.mode)) {
      code.value = JSON.stringify(JSON.parse(code.value), null, 2);
    } else if (["javascript"].includes(codeOptions.mode)) {
      code.value = js_beautify(code.value);
    }
  }

  const $emit = defineEmits(["update:modelValue"]);
  function handleChange(val) {
    _updateFromInner = true;
    $emit("update:modelValue", val);
  }
</script>

<style  scoped>
 
</style>
